package cn.wisteria._stream;

import lombok.Builder;
import lombok.Data;
import lombok.ToString;

import java.util.*;
import java.util.stream.Collectors;

/**
 * <p>
 * Collectors：http://www.itzhimei.com/archives/1453.html。https://blog.csdn.net/lengguoxing/article/details/78415008
 * {@link Collectors#groupingBy}：能对对象进行分组，返回值Map。多次嵌套groupingBy能进行多分组
 * {@link Collectors#averagingInt}：根据某个字段计算平均数。
 * {@link Collectors#minBy}：根据对象中的字段计算最小值。
 * {@link Collectors#summingInt}：根据对象中的字段计算总和。
 * {@link Collectors#summarizingInt}：根据对象中的字段计算汇总信息
 * {@link Collectors#joining}：根据对象中的字段拼接信息。
 * {@link Collectors#partitioningBy}：根据对象中的字段分区。
 * </p>
 *
 * @author: zhu.chen
 * @date: 2021/3/25
 * @version: v1.0.0
 */
public class StramMain {

    public static void main(String[] args) {
        Person person1 = Person.builder().id(1).age(21).name("张三1").build();
        Person person2 = Person.builder().id(2).age(22).name("张三2").build();
        Person person3 = Person.builder().id(3).age(23).name("张三3").build();
        Person person4 = Person.builder().id(4).age(24).name("张三4").build();
        Person person5 = Person.builder().id(5).age(25).name("张三5").build();
        List<Person> list = new ArrayList<>();
        list.add(person1);
        list.add(person2);
        list.add(person3);
        list.add(person4);
        list.add(person5);
        /**
         * [StramMain.Person(id=1, age=21, name=张三1), StramMain.Person(id=2, age=22, name=张三2),
         * StramMain.Person(id=3, age=23, name=张三3), StramMain.Person(id=4, age=24, name=张三4),
         * StramMain.Person(id=5, age=25, name=张三5)]
         */
        System.out.println(list);

        Map<Integer, List<Person>> map = list.stream().collect(Collectors.groupingBy(Person::getId));
        /**
         * {1=[StramMain.Person(id=1, age=21, name=张三1)], 2=[StramMain.Person(id=2, age=22, name=张三2)],
         * 3=[StramMain.Person(id=3, age=23, name=张三3)], 4=[StramMain.Person(id=4, age=24, name=张三4)],
         * 5=[StramMain.Person(id=5, age=25, name=张三5)]}
         */
        System.out.println(map);

        // 23.0
        Double averaging = list.stream().collect(Collectors.averagingInt(Person::getAge));
        System.out.println(averaging);

        // StramMain.Person(id=1, age=21, name=张三1)
        Optional<Person> min = list.stream().collect(Collectors.minBy(Comparator.comparingInt(Person::getAge)));
        System.out.println(min.get());

        // StramMain.Person(id=5, age=25, name=张三5)
        Optional<Person> max = list.stream().collect(Collectors.maxBy(Comparator.comparingInt(Person::getAge)));
        System.out.println(max.get());
        list.stream().collect(Collectors.maxBy(Comparator.comparingInt(Person::getAge))).ifPresent(System.out::println);

        // 115
        Integer sum = list.stream().collect(Collectors.summingInt(Person::getAge));
        System.out.println(sum);

        // intSummaryStatistics = IntSummaryStatistics{count=5, sum=115, min=21, average=23.000000, max=25}
        IntSummaryStatistics intSummaryStatistics = list.stream().collect(Collectors.summarizingInt(Person::getAge));
        System.out.println("intSummaryStatistics = " + intSummaryStatistics);

        // 张三1_张三2_张三3_张三4_张三5
        String name1 = list.stream().map(Person::getName).collect(Collectors.joining("_"));
        System.out.println(name1);

        // [张三1_张三2_张三3_张三4_张三5]
        String name2 = list.stream().map(Person::getName).collect(Collectors.joining("_", "[", "]"));
        System.out.println(name2);

        Map<Integer, Map<String, List<Person>>> groupingBy = list.stream().collect(Collectors.groupingBy(Person::getId, Collectors.groupingBy(Person::getName)));
        /**
         * {1={张三1=[StramMain.Person(id=1, age=21, name=张三1)]}, 2={张三2=[StramMain.Person(id=2, age=22, name=张三2)]},
         * 3={张三3=[StramMain.Person(id=3, age=23, name=张三3)]}, 4={张三4=[StramMain.Person(id=4, age=24, name=张三4)]},
         * 5={张三5=[StramMain.Person(id=5, age=25, name=张三5)]}}
         */
        System.out.println(groupingBy);

        /**
         * {false=[StramMain.Person(id=1, age=21, name=张三1), StramMain.Person(id=2, age=22, name=张三2), StramMain.Person(id=3, age=23, name=张三3)],
         * true=[StramMain.Person(id=4, age=24, name=张三4), StramMain.Person(id=5, age=25, name=张三5)]}
         */
        Map<Boolean, List<Person>> user = list.stream().collect(Collectors.partitioningBy(person -> person.getAge() > 23));
        System.out.println(user);

    }


    @Builder
    @Data
    @ToString
    public static class Person {

        private Integer id;

        private Integer age;

        private String name;

    }

}
